﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;


public delegate void OnConnectedServerEventHandler(ConnectedStatus connectedStatus);
public delegate void OnReceiveSocketDataHnalder(byte[] bytes);

/// <summary>
/// 封装一个异步的Socket连接，参考：https://www.cnblogs.com/supheart/p/4284500.html
/// </summary>
public class XinyueSocketClient
{

    public string host;
    public int port;
    private IPEndPoint endPoint;
    private Socket _socket;
    public event OnConnectedServerEventHandler CompleteConnectServerHandler;
    public event OnReceiveSocketDataHnalder ReceiveSocketDataHandler; 
    public XinyueSocketClient(String host,int port)
    {
        this.host = host;
        this.port = port;
    }
    public void ConnectServer()
    {
        this.Close();
        try
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            this.endPoint = new IPEndPoint(IPAddress.Parse(host), port);
            args.RemoteEndPoint = this.endPoint;
            args.Completed += OnConnectedCompleted;
            _socket.ConnectAsync(args);
        }
        catch(Exception e)
        {
            Debug.Log("服务器连接异常:" + e);
        }
    }


    private void OnConnectedCompleted(object sender,SocketAsyncEventArgs args)
    {
        try
        {
            if (args.SocketError != SocketError.Success)
            {
                CompleteConnectServerHandler?.Invoke(ConnectedStatus.ConnectFailed);
            }
            else
            {
                Debug.Log("网络连接成功线程：" + Thread.CurrentThread.ManagedThreadId.ToString());
                CompleteConnectServerHandler?.Invoke(ConnectedStatus.ConnectedSucess);
                StartReceiveMessage();

            }
        }
        catch(Exception e)
        {
            Debug.Log("开启接收数据异常" + e);
        }
        
    }
    private void StartReceiveMessage()
    {

        //启动接收消息
        SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs();
        byte[] buffer = new byte[1024 * 512];
        receiveArgs.SetBuffer(buffer, 0, buffer.Length);
        receiveArgs.RemoteEndPoint = this.endPoint;
        receiveArgs.Completed += OnReceiveCompleted;
        
        CompleteConnectServerHandler(ConnectedStatus.ConnectedSucess);
        _socket.ReceiveAsync(receiveArgs);
    }


    public void OnReceiveCompleted(object sender,SocketAsyncEventArgs args)
    {
        try
        {
            Debug.Log("网络接收成功线程：" + Thread.CurrentThread.ManagedThreadId.ToString());

            if (args.SocketError == SocketError.Success && args.BytesTransferred > 0)
            {
                byte[] bytes = new byte[args.BytesTransferred];
                Buffer.BlockCopy(args.Buffer, 0, bytes, 0, bytes.Length);
                if(ReceiveSocketDataHandler == null)
                {
                    Debug.Log("没有处理接收消息的事件 ");
                }
                ReceiveSocketDataHandler?.Invoke(bytes);
                StartReceiveMessage();
            }
            else
            {
                CompleteConnectServerHandler(ConnectedStatus.Disconnect);
            }
        }
        catch(Exception e)
        {
            Debug.Log("接收数据异常：" + e);
        }
    }

    public void SendToServer(byte[] data)
    {
        try
        {
            if (_socket == null || !_socket.Connected)
            {
                Debug.Log("socket未连接，发送消息失败");
                return;
            }

            SocketAsyncEventArgs sendEventArgs = new SocketAsyncEventArgs();
            sendEventArgs.RemoteEndPoint = endPoint;
            sendEventArgs.SetBuffer(data, 0, data.Length);
            
            _socket.SendAsync(sendEventArgs);
        }
        catch(Exception e)
        {
            Debug.Log("发送数据异常：" + e);
        } 
    }

    public void Close()
    {
        if(_socket != null)
        {
            _socket.Shutdown(SocketShutdown.Both);
            _socket.Disconnect(false);
            _socket.Close();

        }
    }



}
